﻿using project.B12.application.Ioc;
using project.B12.application.Views.Dialog;
using Software.Common.Util.AppConfig;
using System;
using System.IO;
using System.Reflection;
using System.Runtime.ExceptionServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace project.B12.application
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            if (!IsAlreadyRunning())
            {
                RegisterEvents();

                base.OnStartup(e);

                if (UtilAppConfig.ExistItem("Language"))
                    Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(UtilAppConfig.GetItem("Language") ?? string.Empty);

                IocContainer.Init();
                Application.Current.StartupUri = new Uri("Views/MainWindow.xaml", UriKind.Relative);

                //Application.Current.Shutdown();
            }
            else
            {
                MessageBox.Show("当前程序已运行！");
                Environment.Exit(0);
            }
        }

        /// <summary>
        /// 注册事件
        /// </summary>
        private void RegisterEvents()
        {

            //Task线程内未捕获异常处理事件
            TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;

            //UI线程未捕获异常处理事件（UI主线程）
            this.DispatcherUnhandledException += App_DispatcherUnhandledException;

            //非UI线程未捕获异常处理事件(例如自己创建的一个子线程)
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            AppDomain.CurrentDomain.FirstChanceException += CurrentDomain_FirstChanceException;
        }

        private static void CrashDump(object e)
        {
            if (!Directory.Exists(@"Error\"))
                Directory.CreateDirectory(@"Error\");
            var writer = new StreamWriter(@"Error\" + DateTime.Now.Ticks.ToString() + ".txt");
            writer.Write(e.ToString());
            writer.Close();
            Biotech.Log.LoggerFactory.Instance.CurrentLogger.LogFatal(e.ToString());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void CurrentDomain_FirstChanceException(object sender, FirstChanceExceptionEventArgs e)
        {
            try
            {
                if (e.Exception == null)
                {
                    return;
                }
                if (e.Exception.Message.Contains ("文件缺失或异常")
                    || e.Exception is System.IO.FileNotFoundException
                    )
                {
                    CrashDump(e.Exception);
                    CatchErrorsPrint((e.Exception ).ToString());
                }
                if (e.Exception.Message.Contains("logo.ico"))
                {
                    return;
                }
            }
            catch (Exception ex)
            {
                CrashDump(ex);
            }
        }

        private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            try
            {
                if (e.ExceptionObject == null)
                {
                    return;
                }
                CrashDump(e.ExceptionObject); 
                CatchErrorsPrint((e.ExceptionObject as Exception).ToString());
            }
            catch (Exception ex)
            {
                CrashDump(ex);
            }
        }

        private static void TaskScheduler_UnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)
        {
            try
            {
                if (e.Exception == null)
                {
                    return;
                }
                CrashDump(e.Exception);
            }
            catch (Exception ex)
            {
                CrashDump(ex);
            }
            finally
            {
                e.SetObserved(); 
                CatchErrorsPrint(e.Exception.ToString());
            }
        }

        private static void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            try
            {
               CrashDump(e.Exception);
            }
            catch (Exception ex)
            {
                CrashDump(ex);
            }
            finally
            {
                //处理完后，我们需要将Handler=true表示已此异常已处理过
                e.Handled = true; 
                CatchErrorsPrint(e.Exception.ToString());
            }
        }

        private static Mutex? _mutex;

        private static bool IsAlreadyRunning()
        {
            var strLoc = Assembly.GetExecutingAssembly().Location;
            FileSystemInfo fileInfo = new FileInfo(strLoc);
            var sExeName = fileInfo.Name;
            _mutex = new Mutex(true, "Global\\" + sExeName, out var bCreatedNew);
            if (bCreatedNew)
            {
                _mutex.ReleaseMutex();
            }
            return !bCreatedNew;
        }

        /// <summary>
        /// 致命错误捕获打印
        /// </summary>
        private static void CatchErrorsPrint(string _errors)
        {
            App.Current.Dispatcher.Invoke((Action)(() =>
            {
                ErrorShow _ErrorShow = new ErrorShow();
                // 显示自定义错误窗口
                _ErrorShow.ErrorMessages.Text = _errors;
                _ErrorShow.ShowDialog();
                if (_ErrorShow.IsSafeExit)
                {
                    Environment.Exit(0);
                }
            }));
        }
    }
}
